package model.entity;

import java.util.Iterator;
import java.util.List;
import java.util.Map;

import model.Model;
import model.entity.stats.Stat;
import model.entity.stats.StatSet;
import model.entity.stats.StatType;
import model.item.EquippableItem;
import model.item.EquippedInventory;
import model.item.Inventory;
import model.item.TakeableItem;
import model.map.Direction;
import model.map.Location;
import model.map.MovementType;
import utilities.*;

/**
 * 
 * This is the most basic unit of the idea of an Entity. 
 * Vehicles, NPCs, and Avatar will be created out of this. 
 *
 */
public class BasicEntity extends Model implements Archiveable {

	protected Direction direction;
	protected Location location;
	protected StatSet stats;
	protected List<MovementType> movementTypes;
	protected Inventory inventory;
	protected EquippedInventory equipment;

	public BasicEntity() {
		
	}
	
	public BasicEntity(String name, Direction direction, Location location, StatSet stats, 
			List<MovementType> movementTypes, Inventory inventory, EquippedInventory equipment){

		super(name);
		this.direction = direction;
		this.location = location;
		this.stats = stats;
		this.movementTypes = movementTypes;
		this.inventory = inventory;
		this.equipment = equipment;

	}

	public Direction getDirection() {
		return direction;
	}

	public void setDirection(Direction direction) {
		this.direction = direction;
	}

	public Location getLocation() {
		return location;
	}

	public void setLocation(Location location) {
		this.location = location;
		super.updateSubscribers();
	}

	public StatSet getStats() {
		return stats;
	}
	
	public Stat getStat(String statType)
	{
		return stats.getStat(statType);
	}
	
	public double getStatVal(String statType)
	{
		return stats.getStatVal(statType);
	}

	public void setStats(StatSet stats) {
		this.stats = stats;
	}
	
	public void setStat(String statTypeName, Double val){
		stats.addConstantModifier(statTypeName, val);
	}

	public List<MovementType> getMovementTypes() {
		return movementTypes;
	}

	public void setMovementTypes(List<MovementType> movementTypes) {
		this.movementTypes = movementTypes;
	}

	public Inventory getInventory() {
		return inventory;
	}

	public void setInventory(Inventory inventory) {
		this.inventory = inventory;
		super.updateSubscribers();
	}

	public EquippedInventory getEquipment() {
		return equipment;
	}

	public void setEquipment(EquippedInventory equipment) {
		this.equipment = equipment;
	}
	
	public void addItem(TakeableItem item)
	{
		inventory.addItem(item);
	}
	
	public TakeableItem removeItem(TakeableItem item){
		return inventory.removeItem(item);
	}
	
	public List<TakeableItem> getInventoryItems()
	{
		return getInventory().getItems();
	}
	
	public void addConstantModifier(String type, double modifier) {
		stats.addConstantModifier(type, modifier);
	}
	
	public void addPercentModifier(String type, double modifier) {
		stats.addPercentModifier(type, modifier);
	}

	public void levelUp()
	{
		// TODO Auto-generated method stub
	}
	
	public void EquipItem(EquippableItem item)
	{
		EquippableItem returnedEquipment = equipment.equipItem(item);
		if(returnedEquipment == null)
			;
		else
			this.addItem(returnedEquipment);
    incrementStats(item);
	}
	
	public void UnequipItem(EquippableItem item)
	{
		EquippableItem returnedEquipment = equipment.unequipItem(item);
		if(returnedEquipment == null)
			;
		else
			this.addItem(returnedEquipment);
		decrementStats(item);
	}

	private void incrementStats(EquippableItem item){
		StatSet itemSS = item.getStats();

		Map<String, Stat> itemSSMap = itemSS.getStats();

		Iterator<String> it = itemSSMap.keySet().iterator();
		while (it.hasNext()){
			String stat = it.next();
			this.stats.addConstantModifier(stat, itemSSMap.get(stat).getValue());
		}
	}
	private void decrementStats(EquippableItem item){
		StatSet itemSS = item.getStats();

		Map<String, Stat> itemSSMap = itemSS.getStats();
		
		Iterator<String> it = itemSSMap.keySet().iterator();
		while (it.hasNext()){
			String stat = it.next();
			this.stats.addConstantModifier(stat, -(itemSSMap.get(stat).getValue()));
		}
	}
	
	public Archive save() {
		Archive archive = super.save();
		
//		archive.putClassName("equipment", this.equipment.getClass().getName());
//		archive.putOneRelationship("equipment", this.equipment);
//		
//		archive.putClassName("inventory", this.inventory.getClass().getName());
//		archive.putOneRelationship("inventory", this.inventory);
//		
//		archive.putClassName("location", this.location.getClass().getName());
//		archive.putOneRelationship("location", this.location);
//		
//		archive.putClassName("stats", this.stats.getClass().getName());
//		archive.putOneRelationship("stats", this.stats);
		
		return archive;
	}
	
	public void load(Archive archive) {
//		super.load(archive);
//		
//		this.equipment = (EquippedInventory)ModelFactory.getInstance().createInstanceWithClassName(archive.getClassName("equipment")));
//		this.equipment.load(archive.getOneRelationship("equipment"));
//		
//		this.inventory = (Inventory)ModelFactory.getInstance().createInstanceWithClassName(archive.getClassName("inventory")));
//		this.inventory.load(archive.getOneRelationship("inventory"));
//		
//		this.location = (Location)ModelFactory.getInstance().createInstanceWithClassName(archive.getClassName("location")));
//		this.location.load(archive.getOneRelationship("location"));
//		
//		this.stats = (StatSet)ModelFactory.getInstance().createInstanceWithClassName(archive.getClassName("stats")));
//		this.stats.load(archive.getOneRelationship("stats"));
	}
	 
}

